Solver API

A Model contains Domains, each of which contain Variables defining Fields, and Reactions with ReactionMethods that operate on the Fields to calculate model time evolution.

Create and initialise

PALEOboxes.create_model_from_configMethod
create_model_from_config(
    config_file::AbstractString, configmodel::AbstractString;
    modelpars::Dict = Dict()
) -> model::Model

create_model_from_config(
    config_files,
    configmodel::AbstractString;
    modelpars::Dict = Dict()
) -> model::Model

Construct model from a single YAML config_file, or from a collection of config_files, which are read in order and concatenated before being parsed as yaml.

Optional argument modelpars provides parameters that override those in <configmodel>: parameters: section.

source
PALEOboxes.ModelDataType
ModelData(model::Model; arrays_eltype::DataType=Float64, threadsafe::Bool=false, allocatenans::Bool=true)

Create a ModelData struct containing model data arrays.

One set of data arrays is created with eltype=arrays_eltype, accessed with arrays_idx=1

Additional sets of data arrays may be added by push_arrays_data!, eg in order to support automatic differentiation which requires Dual numbers as the array element type.

Fields

  • cellranges_all::Vector{AbstractCellRange}: default cellranges covering all domains
  • dispatchlists_all: default dispatchlists covering all domains
  • solver_view_all: optional untyped context field for use by external solvers.
source
PALEOboxes.push_arrays_data!Function
push_arrays_data!(modeldata, arrays_eltype::DataType, arrays_tagname::AbstractString)

Add an (unallocated) additional array set with element type arrays_eltype.

source
PALEOboxes.allocate_variables!Function
allocate_variables!(
    vars, modeldata, arrays_idx; 
    [, eltypemap::Dict{String, DataType}],
    [, default_host_dependent_field_data=nothing],
    [, allow_base_link=true],
    [. use_base_transfer_jacobian=true],
    [, use_base_vars=String[]],
    [, check_units_opt=:no])

Allocate or link memory for VariableDomains vars in modeldata array set arrays_idx

Element type of allocated Arrays is determined by eltype(modeldata, arrays_idx) (the usual case, allowing use of AD types), which can be overridden by Variable :datatype attribute if present (allowing Variables to ignore AD types). :datatype may be either a Julia DataType (eg Float64), or a string to be looked up in eltypemap.

If allow_base_link==true, and any of the following are true a link is made to the base array (arrays_idx=1), instead of allocating a new array in array set arrays_idx: - Variable element type matches modeldata base eltype (arraysidx=1) - `usebasetransferjacobian=trueand Variable:transferjacobianattribute is set - Variable full name is inusebase_vars`

Field data type is determined by Variable :field_data attribute, optionally this can take a default_host_dependent_field_data default for Variables with host_dependent(v)==true (these are Variables with no Target or no Property linked, intended to be external dependencies supplied by the solver).

If check_units_opt != :no then the :units field of linked variable is checked, resulting in either a warning (if check_units_opt=:warn) or error (if check_units_opt=:error).

source
allocate_variables!(model, modeldata, arrays_idx; kwargs...)

Allocate memory for Domain variables for every Domain in model.

See allocate_variables!(domain::Domain, modeldata::AbstractModelData, arrays_idx::Int).

source
allocate_variables!(domain, modeldata, arrays_idx; [hostdep=false] [, kwargs...])

Allocate memory for Domain Variables.

If hostdep=false, only internal Variables are allocated, allowing host-dependent Variables (usually state Variables and derivatives + any external dependencies) to be set to views on host-managed arrays.

See allocate_variables!(vars, modeldata::AbstractModelData, arrays_idx::Int).

source
PALEOboxes.check_readyMethod
check_ready(model, modeldata; [throw_on_error=true] [, check_hostdep_varnames=true] [, expect_hostdep_varnames=["global.tforce"]]) -> ready

Check all variable pointers set, and no unexpected host-dependent non-state Variables (ie unlinked Variables)

source
PALEOboxes.initialize_reactiondata!Method
initialize_reactiondata!(model::Model, modeldata::AbstractModelData; kwargs...)

Processes VarList_...s from ReactionMethods and populates modeldata.sorted_methodsdata_... with sorted lists of ReactionMethods and corresponding Variable accessors.

Optionally calls create_dispatch_methodlists(model, modeldata, modeldata.cellranges_all) to set modeldata.dispatchlists_all to default ReactionMethodDispatchLists for entire model.

Keyword arguments

  • arrays_indices=1:num_arrays(modeldata): modeldata arrays_idx to generate dispatch lists for
  • create_dispatchlists_all=false: true to set modeldata.dispatchlists_all
  • generated_dispatch=true: true to use autogenerated code for modeldata.dispatchlists_all (fast dispatch, slow compile)
source
PALEOboxes.dispatch_setupFunction
dispatch_setup(model, attribute_name, modeldata, cellranges=modeldata.cellranges_all)

Call setup methods, eg to initialize data arrays (including state variables).

attribute_name defines the setup operation performed. dispatch_setup should be called in sequence with attribute_name = :

  • :setup: initialise Reactions and set up any non-state Variables (eg model grid Variables) (applied to modeldata arrays_idx=1, values then copied to other arrays_idx)
  • :norm_value: set state Variable values from :norm_value attribute in .yaml file, and initialise any Reaction state that requires this value (arrays_idx 1 only)
  • :initial_value (optional): set state Variable values from :initial_value attribute in .yaml file (arrays_idx 1 only)
source
PALEOboxes.create_dispatch_methodlistsFunction
create_dispatch_methodlists(model::Model, modeldata::AbstractModelData, arrays_idx::Int, cellranges; kwargs) 
    -> DispatchMethodLists(list_initialize, list_do)

Compile lists of initialize and do methods + corresponding cellrange for main loop do_deriv.

Subset of methods and cellrange to operate on are generated from supplied cellranges.

Keyword arguments

  • verbose=false: true for additional log output
  • generated_dispatch=true: true to create ReactionMethodDispatchLists (fast dispatch using generated code, slow compile time), false to create ReactionMethodDispatchListNoGen (slow dynamic dispatch, fast compile time)
source

Attaching numerical solvers

High-level access to aggregated collections of Variables is provided by VariableAggregator and VariableAggregatorNamed (see Accessing model objects for low-level access).

PALEOboxes.VariableAggregatorType
VariableAggregator(vars, cellranges, modeldata, arrays_idx) -> VariableAggregator

Aggregate multiple VariableDomains into a flattened list (a contiguous Vector).

Creates a VariableAggregator for collection of Variables vars, with indices from corresponding cellranges, for data arrays in modeldata with arrays_idx.

cellranges may contain nothing entries to indicate whole Domain.

This is mostly useful for aggregating state Variables, derivatives, etc to implement an interface to a generic ODE/DAE etc solver.

Values may be copied to and from a Vector using copyto!

source
PALEOboxes.get_indicesFunction
get_indices(va::VariableAggregator, varnamefull::AbstractString; allow_not_found=false) -> indices::UnitRange{Int64}

Return indices in flattened Vector corresponding to Variable varnamefull

source
Base.copyto!Method
copyto!(dest::VariableAggregator, src::AbstractVector; sof=1) -> num_copied::Int

Set aggregated Variables dest = (contiguous) Vector src.

Optional sof sets first index in src to use.

source
Base.copyto!Method
copyto!(dest::AbstractVector, va::VariableAggregator; dof=1) -> num_copied::Int

Set (contiguous) Vector dest = aggregated Variables src

Optional dof sets first index in dest

source
PALEOboxes.VariableAggregatorNamedType
VariableAggregatorNamed(modeldata, arrays_idx=1) -> VariableAggregatorNamed
VariableAggregatorNamed(vars, modeldata, arrays_idx=1) -> VariableAggregatorNamed
VariableAggregatorNamed(va::VariableAggregator; ignore_cellranges=false) -> VariableAggregatorNamed

Aggregate VariableDomains into nested NamedTuples, with Domain and Variable names as keys and data arrays (from get_data) as values.

Any / characters in Variable names are replaced with __ (double underscore)

This provides direct access to Variables by name, and is mostly useful for testing or for small models.

Fields

  • vars: nested NamedTuples (domainname, varname) of VariableDomains
  • values: nested NamedTuples (domainname, varname) of data arrays.
source

Aggregated collections of a subset of Parameters as a flattened Vector (eg for sensitivity studies) is provided by ParameterAggregator:

PALEOboxes.ParameterAggregatorType
ParameterAggregator(parfullnames::Vector{String}, model; eltype=Float64) -> ParameterAggregator

Represent a subset of model parameters given by parfullnames as a flattened Vector

parfulnames is a Vector of form ["domainname.reactionname.parname", ...] defining a subset of model parameters (NB: must be of type ParDouble or ParDoubleVec ie scalar or vector of Float64).

norm_values can be used to specify normalisation of the flattened parameter vector (defaults to 1.0).

The parameters can then be set from and copied to a flattened Vector using:

copyto!(pa::ParameterAggregator, newvalues::Vector)  # set from newvalues .* norm_values
copyto!(currentvalues::Vector, pa::ParameterAggregator) # copy to currentvalues, dividing by norm_values
get_currentvalues(pa::ParameterAggregator) -> currentvalues::Vector

The subset of parameters are then defined by the p parameter Vector used by SciML solvers, and combined with the full set (from the yaml file) to eg solve an ODE to enable sensitivity studies.

eltype can be eg a Dual number to support ForwardDiff automatic differentiation for parameter Jacobians.

source

Defining CellRanges

PALEOboxes.AbstractCellRangeType
AbstractCellRange

Defines a range of cells within a Domain.

Fields

All implementations should define:

  • domain::Domain: the Domain covered by this cellrange.
  • operatorID::Int: If operatorID==0, call all Reactions, otherwise only call those with matching operatorID (this enables operator splitting).
  • indices: an iterable list of cell indices.

And then may provide subtype-specific fields defining additional ranges of cells.

source
PALEOboxes.CellRangeType
CellRange <: AbstractCellRange

Defines a range of cells in a specified Domain as a linear list.

Fields

  • domain

  • operatorID

  • indices: may be any valid Julia indexing range thing eg 1:100, [1 2 3 4], etc

source
PALEOboxes.CellRangeColumnsType
CellRangeColumns <: AbstractCellRange

Defines a range of cells in a specified Domain, organised by columns.

Fields

  • domain

  • operatorID

  • indices: iterator through all cells in arbitrary order

  • columns: iterator through columns: columns[n] returns a Pair icol=>cells where cells are ordered top to bottom

source
PALEOboxes.Grids.create_default_cellrangeFunction
create_default_cellrange(domain, grid, [; operatorID=0]) -> CellRange

Create a CellRange for entire domain and supplied operatorID

source
create_default_cellrange(domain, grid::Nothing [; operatorID=0]) -> CellRange

Create a CellRange for entire domain. Fallback for a domain with no grid

source
create_default_cellrange(domain, grid::UnstructuredVectorGrid [; operatorID=0]) -> CellRange

Create a CellRange for entire domain - use linear index.

source
create_default_cellrange(domain, grid::UnstructuredColumnGrid [; operatorID=0]) -> CellRangeColumns

Create a CellRange for entire domain. Return a PB.CellRangeColumns with iterators for columns and cells.

source
create_default_cellrange(domain, grid::Union{CartesianLinearGrid, CartesianArrayGrid} [; operatorID=0]) -> CellRangeColumns

Create a CellRange for entire domain. Return a PB.CellRangeColumns provided by cellrange_cartesiantile

source
PALEOboxes.Grids.cellrange_cartesiantileFunction
cellrange_cartesiantile

Create a range of cells within a region of CartesianLinearGrid specified by rangestuple in a specified PB.Domain

rangestuple is a tuple of Cartesian index ranges eg (1:9, :, :) for a 3D grid.

source

3D case return a CellRangeColumns

source

return partitioning of a 3D Domain into n tiles

source

Main loop

PALEOboxes.do_derivFunction
do_deriv(dispatchlists, deltat::Float64=0.0)
do_deriv(dispatchlists, pa::ParameterAggregator, deltat::Float64=0.0)

Wrapper function to calculate entire derivative (initialize and do methods) in one call. dispatchlists is from create_dispatch_methodlists.

source
PALEOboxes.dispatch_methodlistFunction
dispatch_methodlist(dl::ReactionMethodDispatchList, deltat::Float64=0.0)
dispatch_methodlist(dl::ReactionMethodDispatchList, pa::ParameterAggregator, deltat::Float64=0.0)
dispatch_methodlist(dl::ReactionMethodDispatchListNoGen, deltat::Float64=0.0)
dispatch_methodlist(dl::ReactionMethodDispatchListNoGen, pa::ParameterAggregator, deltat::Float64=0.0)

Call a list of ReactionMethods.

Implementation

As an optimisation, with dl::ReactionMethodDispatchList uses @generated for Type stability and to avoid dynamic dispatch, instead of iterating over lists.

ReactionMethodDispatchList fields are Tuples hence are fully Typed, the @generated function emits unrolled code with a function call for each Tuple element.

source

Diagnostics

PALEOboxes.show_linksFunction
show_links(vardom::VariableDomain)
show_links(model::Model, varnamefull::AbstractString)
show_links(io::IO, vardom::VariableDomain)
show_links(io::IO, model::Model, varnamefull::AbstractString)

Display all VariableReactions linked to this VariableDomain

varnamefull should be of form "<domain name>.<variable name>"

Linked variables are shown as "<domain name>.<reaction name>.<method name>.<local name>"

source
PALEOboxes.show_parametersFunction
show_parameters(model) -> DataFrame

Get parameters for all reactions in model.

Examples:

Show all model parameters using VS Code table viewer:

julia> vscodedisplay(PB.show_parameters(run.model))

Write out all model parameters as csv for import to a spreadsheet:

julia> CSV.write("pars.csv", PB.show_parameters(run.model))
source
show_parameters(react::AbstractReaction) -> DataFrame
show_parameters(classname::AbstractString) -> DataFrame

list all parameters for a Reaction react instance or classname

source

Accessing model objects

Model

PALEOboxes.get_domainFunction
get_domain(model::Model, name::AbstractString; allow_not_found=true) -> Domain or nothing
get_domain(model::Model, domainid) -> Domain

Get Domain by name (may be nothing if name not matched) or domainid (range 1:num_domains).

source
PALEOboxes.get_reactionMethod
get_reaction(model::Model, domainname, reactionname; allow_not_found=false) -> Reaction or nothing

Get Reaction by domainname and reaction name

source
PALEOboxes.set_variable_attribute!Function
set_variable_attribute!(model::Model, varnamefull, attributename::Symbol, value)

Set varnamefull (of form <domain name>.<var name>) attributename to value.

source
PALEOboxes.get_variable_attributeFunction
get_variable_attribute(model::Model, varnamefull, attributename::Symbol, missing_value=missing) -> attributevalue

Get varnamefull (of form <domain name>.<var name>) attributename.

source

Domains

PALEOboxes.get_variablesFunction
get_variables(varlist::AbstractVarList; flatten=true) -> Vector{VariableReaction}

Return VariableReaction in varlist.

If flatten=true, a Vector-of-Vectors is flattened.

source
get_variables(domain; hostdep=nothing, vfunction=VF_Undefined) -> Vector{VariableDomain}

Get domain variables, optionally filtering for subsets based on hostdep and :vfunction attribute

source
get_variables(domain, filter) -> Vector{VariableDomain}

Get subset of domain variables where filter(var) == true.

source
get_variables(method::AbstractReactionMethod; filterfn = v -> true) -> Vector{VariableReaction}

Get VariableReactions from method.varlists as a flat Vector, optionally restricting to those that match filterfn

source
get_variables(reaction, localname) -> Vector{VariableReaction}
get_variables(reaction; [filterfn=v->true]) -> Vector{VariableReaction}

Get matching Variables from all ReactionMethods.

source
PALEOboxes.get_host_variablesFunction
get_host_variables(domain, vfunction; [match_deriv_suffix=""] [, operatorID=0] [, exclude_var_nameroots=[]] [, verbose=false]) 
    -> (host_vars, host_deriv_vars)

Get state Variables with VariableFunction vfunction, and optionally corresponding time derivative with VariableFunction VF_Deriv and name matching hostvarname*<match_deriv_suffix`>.

Optionally filter by operatorID, omit Variables with name matching exclude_var_nameroots.

source
PALEOboxes.get_unallocated_variablesFunction
get_unallocated_variables(domain, modeldata, arrays_idx::Int) -> Vector{VariableDomain}

Return any unallocated variables (host-dependent variables which have no data pointer set)

source

VariableDomain

Low-level access to individual Variables.

PALEOboxes.get_dataFunction
get_data(var::VariableDomain, modeldata::AbstractModelData, arrays_idx::Int=1) -> field.values
get_data(var::VariableDomain, domaindata::AbstractDomainData) -> field.values

Get Variable var data array from Field.values

source
get_data(va::VariableAggregator) -> Vector

Allocate Vector and set to values of aggregated Variables va.

source
PALEOboxes.get_data_outputFunction
get_data(var::VariableDomain, modeldata::AbstractModelData, arrays_idx::Int) -> get_values_output(field.values)
get_data(var::VariableDomain, domaindata::AbstractDomainData) -> get_values_output(field.values)

Get a sanitized version of Variable var data array for storing as output from [get_values_output]@ref)(Field.values)

source